package com.lsh.service.impl;

import com.lsh.dao.CommentDao;
import com.lsh.dao.PraiseDao;
import com.lsh.dao.UserTokenDao;
import com.lsh.domain.UserPraise;
import com.lsh.mq.PraiseProducer;
import com.lsh.service.PraiseService;
import com.lsh.util.PraiseRedisUtil;
import net.sf.json.JSONObject;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.jms.Destination;
import java.util.Set;

import static com.lsh.util.PraiseRedisUtil.PRAISE_COMMENT_KEY;

/**
 * 点赞模块(高并发)
 * @author Administrator
 * @date 2019/10/01 1:25
 */
@Service
public class PraiseServiceImpl implements PraiseService {

    @Resource
    RedisTemplate redisTemplate;

    @Autowired
    UserTokenDao userTokenDao;

    @Autowired
    CommentDao commentDao;

    @Autowired
    PraiseDao praiseDao;

    //队列
    private static Destination destination = new ActiveMQQueue("queue.comment.praise");
    @Resource
    private PraiseProducer praiseProducer;

    /**
     * 点赞评价
     * @param token
     * @param commentId
     * @return
     */
    @Override
    public String praiseComment(String token, String commentId) {
        String message = null;
        String userId = userTokenDao.getByToken(token);

        //发送消息
        praiseProducer.sendMessage(destination, new UserPraise(commentId, userId));

        redisTemplate.opsForSet().add(PRAISE_COMMENT_KEY, commentId);
        Boolean member = redisTemplate.opsForSet().isMember(PraiseRedisUtil.PRAISE_COMMENT_USER_ID_KEY + commentId, userId);
        if(member){ //redis中存在该点赞记录
            if("0".equals(redisTemplate.opsForHash().get(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_MAP, commentId + "::" + userId))) { //满足则表示当前为点赞
                redisTemplate.opsForHash().put(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_MAP, commentId + "::" + userId, "1");
                redisTemplate.opsForHash().increment(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_COUNT, commentId, 1); //统计在redis中评价的点赞数+1
                message = "1";
            } else{ //否则为取消点赞
                redisTemplate.opsForHash().put(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_MAP, commentId + "::" + userId, "0");
                redisTemplate.opsForHash().increment(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_COUNT, commentId, -1); //统计在redis中评价的点赞数-1
                message = "-1";
            }
        }else{ //redis不存在该点赞记录，需要先从数据库查询
            int praise = commentDao.findPraise(userId, commentId);
            if(praise>0){ //数据库中存在该点赞记录
                redisTemplate.opsForSet().add(PraiseRedisUtil.PRAISE_COMMENT_USER_ID_KEY + commentId, userId); //记录用户操作
                redisTemplate.opsForHash().put(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_MAP, commentId + "::" + userId, "0"); //由于数据库已存在该记录则当前为取消点赞
                redisTemplate.opsForHash().increment(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_COUNT, commentId, -1); //统计在redis中评价的点赞数-1
                message = "-1";
            }else{ //数据库中不存在该点赞记录
                redisTemplate.opsForSet().add(PraiseRedisUtil.PRAISE_COMMENT_USER_ID_KEY + commentId, userId); //记录用户操作
                redisTemplate.opsForHash().put(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_MAP, commentId + "::" + userId, "1"); //由于数据库不存在该记录则当前为点赞
                redisTemplate.opsForHash().increment(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_COUNT, commentId, 1); //统计在redis中评价的点赞数+1
                message = "1";
            }
        }
        JSONObject jo = new JSONObject();
        jo.put("code", 200);
        jo.put("message", message);
        return jo.toString();
    }

    /**
     * 点赞回复
     * @param token
     * @param replyId
     * @return
     */
    @Override
    public String praiseReply(String token, String replyId) {
        return null;
    }

    /**
     * 查询被点赞评价和点赞用户是否存在点赞记录
     * @param commentId
     * @param userId
     * @return
     */
    @Override
    public UserPraise getByPraiseCommentIdAndUserId(String commentId, String userId) {
        return praiseDao.findPraise(commentId, userId);
    }

    /**
     * 将redis中的点赞数据和点赞记录数存到数据库中
     */
    @Override
    public void praiseDataFToDB() {
        Set<String> commentIds = redisTemplate.opsForSet().members(PraiseRedisUtil.PRAISE_COMMENT_KEY);
        if(CollectionUtils.isEmpty(commentIds)){
            System.out.println("--Redis暂无相应数据--");
            return;
        }
        for(String commentId: commentIds){
            if(redisTemplate.opsForSet().members(PraiseRedisUtil.PRAISE_COMMENT_USER_ID_KEY + commentId) == null){
                continue;
            }else{
                // 保存点赞数据
                Set<String> userIds = redisTemplate.opsForSet().members(PraiseRedisUtil.PRAISE_COMMENT_USER_ID_KEY + commentId);
                if(CollectionUtils.isEmpty(userIds)) {
                    continue;
                } else{
                    for(String userId: userIds) {
                        String praise = (String) redisTemplate.opsForHash().get(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_MAP, commentId + "::" + userId);
                        if(StringUtils.isEmpty(praise)){
                            continue;
                        }
                        UserPraise userPraise = getByPraiseCommentIdAndUserId(commentId, userId);
                        if(userPraise != null && "0".equals(praise)){
                            // 将数据库的该数据删除
                            praiseDao.deletePraise(userPraise);

                        }else if(userPraise == null && "1".equals(praise)){
                            Integer cid = praiseDao.findByCommentId(commentId);
                            if(cid != null && cid > 0){
                                userPraise = new UserPraise(commentId, userId);
                                // 将该数据存到数据库中
                                praiseDao.savePraise(userPraise);
                            }
                        }
                        //删除该数据的缓存
                        redisTemplate.opsForHash().delete(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_MAP, commentId + "::" + userId);
                    }
                    // 保存点赞记录数
                    Integer dbCommentCount = praiseDao.findByCommentCount(commentId);
                    if(dbCommentCount != null) { //当查找不到该评价id的点赞数，则直接跳过（出现的原因有该评价被删除的情况）
                        int praiseCount =  + Integer.parseInt((String)redisTemplate.opsForHash().get(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_COUNT, commentId));
                        praiseDao.updateCommentCount(commentId, praiseCount);
                    }
                    //删除该数据的缓存
                    redisTemplate.delete(PraiseRedisUtil.PRAISE_COMMENT_USER_ID_KEY + commentId);
                }
            }
        }
        //删除该数据的缓存
        redisTemplate.delete(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_MAP);
        redisTemplate.delete(PraiseRedisUtil.PRAISE_COMMENT_USER_LIKE_COUNT);
        redisTemplate.delete(PraiseRedisUtil.PRAISE_COMMENT_KEY);
        System.out.println("--保存完成--");
    }

}
